# install.packages("tidyverse");
# install.packages("rgdal");
library(tidyverse)
require("maps")
library(geosphere)
library(stringr)
library(rgdal)
library(caret)
library(lubridate)
if (!require(ggmap)) { install.packages('ggmap'); require(ggmap) }
path.to.csv <- '../Milestone 2/Seattle_Police_Department_911_Incident_Response_Oct17.csv'
spd.911 <- read.csv(path.to.csv, TRUE)
spd.911$clearance_date_ts = as.POSIXct(strptime(spd.911$Event.Clearance.Date, "%m/%d/%Y %I:%M:%S %p"))
spd.911$clearance_date_date = as.Date(spd.911$clearance_date_ts)
# View(spd.911)
# path to the FOLDER with the .shp file in it. the second param is the name of the .shp file
# seattle <- readOGR(dsn = path.expand("~/documents/INFO370/project-teamname-v2/maps-api-test"), layer = "Seattle_City_Limits")
# usa <- map_data("state")
# data <- merge(usa, spd.911)
here_long <- -122.30
here_lat <- 47.66
seattle = get_map(location = c(here_long, here_lat), zoom = 13, maptype = 'roadmap')
Map from URL : http://maps.googleapis.com/maps/api/staticmap?center=47.66,-122.3&zoom=13&size=640x640&scale=2&maptype=roadmap&language=en-EN&sensor=false
spd.911 <- spd.911 %>%
rowwise() %>%
mutate(dist=distVincentyEllipsoid(c(Longitude, Latitude), c(here_long, here_lat)))
nrow(spd.911)
[1] 20197
descriptions <- c("STRONG ARM ROBBERY", "PERSON WITH A WEAPON (NOT GUN)", "HAZARDS", "HARRASMENT, THREATS", "FIGHT DISTURBANCE", "CRISIS COMPLAINT - GENERAL", "ARMED ROBBERY")
data.ped <- spd.911 %>% filter(str_detect(Event.Clearance.Description, paste(descriptions, collapse="|")))
# data.ped <- data.now
nrow(data.ped)
[1] 1068
data.now <- data.ped %>% filter(clearance_date_ts < '2017-10-31 00:00:00')
nrow(data.now)
[1] 1068
data.here <- data.now %>% filter(dist < 4600)
data <- data.here
nrow(data)
[1] 154
# View(data)
ggmap(seattle) +
geom_point(data = data, aes(x = Longitude, y = Latitude), colour = "red", alpha = 0.75)

#coord_map()
freq_by_desc <- table(droplevels(data$Event.Clearance.Description))
# View(freq_by_desc)
ggplot(as.data.frame(freq_by_desc),
aes(x = Var1, y = Freq)) +
geom_bar(stat = 'identity') +# create bar plot
coord_flip()

#Traffic related calls, suspicious circumstances, and disturbances are the the most significant threats to pedestrations
ggmap(seattle) +
geom_point(data = data, aes(x = Longitude, y = Latitude, group = Event.Clearance.Description, color = Event.Clearance.Description), alpha = 0.5) +
facet_wrap(~ Event.Clearance.Description) +
theme(axis.ticks = element_blank(),
axis.text.x = element_blank(),
axis.text.y = element_blank(),
legend.position = "none"
)

# selecting just ID and location data
df_loc <- data %>% dplyr::select(CAD.CDW.ID, Longitude, Latitude)
# figuring out number of clusters
wss <- c()
# clusters 1 to 15
for (i in 1:15) {
wss[i] <- sum(kmeans(df_loc, centers=i)$withinss)
}
plot(1:15, wss, type="b", xlab="Number of Clusters",
ylab="Within groups sum of squares")

# fitting model
fit <- kmeans(df_loc, 10)
fit$centers # look at cluster sizes and means. want clusters to be about equal size
CAD.CDW.ID Longitude Latitude
1 2114598 -122.3178 47.65411
2 2109759 -122.3121 47.65562
3 2111482 -122.3199 47.65574
4 2115977 -122.3118 47.65820
5 2117842 -122.3182 47.65687
6 2120071 -122.3184 47.65099
7 2107842 -122.3248 47.65292
8 2123882 -122.3193 47.65530
9 2112892 -122.3230 47.66317
10 2105812 -122.3212 47.66055
fit$cluster
[1] 10 10 10 10 10 10 10 10 10 10 10 10 10 7 7 7 7 7 7 7 7 7 7 7 7 7 7 2 2 2 2 2 2
[34] 9 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 9 9 9 9 9 9 9 9 9 1
[67] 1 1 1 1 1 1 1 1 1 1 1 1 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 5 5 5
[100] 5 5 5 5 5 5 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
[133] 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8
cluster.size <- data.frame(1:10, fit$size)
cluster.size
ggplot(data = cluster.size, aes(x = X1.10, y = fit.size)) +
geom_bar(stat = 'identity')

ggplot()

ggmap(seattle) +
geom_point(data = as.data.frame(fit$centers), aes(x = Longitude, y = Latitude), alpha = 0.5)

# looking at cluster means
aggregate(df_loc, by=list(fit$cluster), FUN=mean)
df_loc
# adding data back into dataframe
# df_loc <- df_loc %>% mutate(cluster = fit$cluster)
data$cluster <- fit$cluster
# View(data)
# timestamp -> year month day hour minute
# sector -> to factor (there are 17 sectors)
# beat -> to factor (there are 3 beats per sector)
# clean the data a bit more
data$event_clearance_ts = as.POSIXct(strptime(data$Event.Clearance.Date, "%m/%d/%Y %I:%M:%S %p"))
data$event_clearance_date = as.Date(data$event_clearance_ts)
data$event_clearance_month = month(ymd_hms(as.character(data$event_clearance_ts)))
data$event_clearance_day = weekdays(data$event_clearance_date)
data$event_clearance_hr = hour(ymd_hms(as.character(data$event_clearance_ts)))
data$event_clearance_mn = minute(ymd_hms(as.character(data$event_clearance_ts)))
data$Initial.Type.Group = factor(data$Initial.Type.Group)
data$Event.Clearance.Group = factor(data$Event.Clearance.Group)
data$Zone.Beat = factor(data$Zone.Beat)
data$District.Sector = factor(data$District.Sector)
data$event_clearance_day = factor(data$event_clearance_day)
data
col.names <- paste(c(
"Event.Clearance.Code"
, "cluster"
, "Census.Tract"
, "event_clearance_day"
, "Event.Clearance.Group"
, "Event.Clearance.SubGroup"
, "District.Sector"
, "Zone.Beat"
#, "event_clearance_ts"
# ,"Incident.Location"
, "event_clearance_hr"
, "event_clearance_mn"
, "event_clearance_month"
, "Hundred.Block.Location"
), collapse="|")
cols <- grep(col.names, colnames(data))
cols
[1] 4 6 7 9 10 11 12 23 26 27 28 29
# corr_matrix <- cor(data[,cols]) # correlations between all predictor vars
# corr_matrix
# cutoff <- 0.5 # should be higher in practice
# highly_corr <- findCorrelation(corr_matrix, cutoff=cutoff)
# print(colnames(spd.911)[highly_corr]) # age is highly correalted with pregnant
train.data <- select(data, cols)
train.data
# data <- data %>% droplevels()
# grep("Hundred.Block.Location", colnames(train.data), invert = T)
predictors <- grep("Hundred.Block.Location", colnames(train.data), invert = T)
outcome <- grep("Hundred.Block.Location", colnames(train.data))
# train.data[,predictors]
frame <- data.frame(train.data[,predictors])
frame
out.factor <- train.data$Hundred.Block.Location
as.vector(out.factor)
[1] "43XX BLOCK OF 15 AV NE" "24XX BLOCK OF E LOUISA ST"
[3] "FREMONT BR / SB" "48XX BLOCK OF SAND POINT WY NE"
[5] "42XX BLOCK OF UNIVERSITY WY NE" "21XX BLOCK OF N NORTHLAKE WY"
[7] "14XX BLOCK OF NE 43 ST" "BRIDGE WY N / N 38 ST"
[9] "8XX BLOCK OF NE 95 ST" "14XX BLOCK OF NE 43 ST"
[11] "17XX BLOCK OF N 45 ST" "NE 54 ST / 21 AV NE"
[13] "6XX BLOCK OF N 50 ST" "AURORA BR / SB"
[15] "FAIRVIEW AV N / ALOHA ST" "77XX BLOCK OF SAND POINT WY NE"
[17] "11XX BLOCK OF N 81 ST" "AURORA AV N / GARFIELD ST"
[19] "SAND POINT WY NE / 40 AV NE" "55XX BLOCK OF 12 AV NE"
[21] "BRIDGE WY N / AURORA BR" "3 AV NW / NW 45 ST"
[23] "NE 43 ST / UNIVERSITY WY NE" "E ROANOKE ST / I5 NB"
[25] "49XX BLOCK OF AURORA AV N" "15 AV E / E REPUBLICAN ST"
[27] "5XX BLOCK OF 15 AV E" "E HAMLIN ST / EASTLAKE AV E"
[29] "71XX BLOCK OF 12 AV NE" "VALLEY ST / FAIRVIEW AV N"
[31] "7XX BLOCK OF BROADWAY E" "SUNNYSIDE AV N / E GREEN LAKE DR N"
[33] "NE 95 ST / 35 AV NE" "85XX BLOCK OF 20 AV NE"
[35] "N 48 ST / GREENWOOD AV N" "80XX BLOCK OF SAND POINT WY NE"
[37] "41 AV E / E BLAINE ST" "84XX BLOCK OF 35 AV NE"
[39] "23XX BLOCK OF 24 AV E" "50XX BLOCK OF UNIVERSITY WY NE"
[41] "4XX BLOCK OF 15 AV E" "E MONTLAKE PL E / E LAKE WASHINGTON BV"
[43] "14XX BLOCK OF NE 43 ST" "3XX BLOCK OF NICKERSON ST"
[45] "16XX BLOCK OF INTERLAKEN PL E" "91XX BLOCK OF ROOSEVELT WY NE"
[47] "8XX BLOCK OF NE 66 ST" "22XX BLOCK OF E MADISON ST"
[49] "44XX BLOCK OF 52 AV NE" "NE 47 ST / 17 AV NE"
[51] "4 AV N / QUEEN ANNE DR" "N 90 ST / MERIDIAN AV N"
[53] "4XX BLOCK OF BOYLSTON AV E" "11XX BLOCK OF FAIRVIEW AV N"
[55] "45XX BLOCK OF 16 AV NE" "FLORENTIA ST / NICKERSON ST"
[57] "42XX BLOCK OF WHITMAN AV N" "47XX BLOCK OF UNIVERSITY WY NE"
[59] "NE 50 ST / 9 AV NE" "45XX BLOCK OF 25 AV NE"
[61] "61XX BLOCK OF BROOKLYN AV NE" "AURORA AV N / N 68 ST"
[63] "E GALER ST / FRANKLIN AV E" "45XX BLOCK OF UNIVERSITY WY NE"
[65] "AURORA BR / NB" "15 AV NE / NE 55 ST"
[67] "10XX BLOCK OF E THOMAS ST" "NE 45 ST / 11 AV NE"
[69] "2 AV NE / NE 50 ST" "11 AV NE / NE 42 ST"
[71] "NE BLAKELEY ST / 25 AV NE" "25XX BLOCK OF E ROY ST"
[73] "4213 1 / 2 UNIVERSITY WY NE" "15 AV NE / NE 42 ST"
[75] "73XX BLOCK OF ROOSEVELT WY NE" "NE 47 ST / 9 AV NE"
[77] "AURORA AV N / FREMONT WY N" "YALE AV N / MERCER ST"
[79] "NE 45 ST / 5 AV NE" "NE 52 ST / 15 AV NE"
[81] "47XX BLOCK OF 30 AV NE" "AURORA BR / SB"
[83] "UNIVERSITY WY NE / NE 56 ST" "22XX BLOCK OF E MADISON ST"
[85] "ROOSEVELT WY NE / NE 45 ST" "50XX BLOCK OF UNIVERSITY WY NE"
[87] "41XX BLOCK OF UNIVERSITY WY NE" "27XX BLOCK OF MONTLAKE BV E"
[89] "14XX BLOCK OF N 42 ST" "NE WINDERMERE RD / SAND POINT WY NE"
[91] "12XX BLOCK OF 15 AV E" "3 AV N / NICKERSON ST"
[93] "42XX BLOCK OF UNIVERSITY WY NE" "35 AV NE / NE 95 ST"
[95] "NE 55 ST / 45 AV NE" "24XX BLOCK OF E LOUISA ST"
[97] "69XX BLOCK OF 62 AV NE" "55XX BLOCK OF NE 58 ST"
[99] "37XX BLOCK OF CORLISS AV N" "E INTERLAKEN BV / LAKE WASHINGTON BV E"
[101] "AURORA BR / SB" "AURORA AV N / N 50 ST"
[103] "45XX BLOCK OF 18 AV NE" "NE 50 ST / 2 AV NE"
[105] "NEWTON ST / WESTLAKE AV N" "WOODLAWN AV N / N 63 ST"
[107] "AURORA BR / SB" "73XX BLOCK OF E GREEN LAKE DR N"
[109] "38XX BLOCK OF AURORA AV N" "14 AV E / E JOHN ST"
[111] "73XX BLOCK OF 35 AV NE" "NE 70 ST / 15 AV NE"
[113] "45XX BLOCK OF 25 AV NE" "48XX BLOCK OF SAND POINT WY NE"
[115] "45XX BLOCK OF 9 AV NE" "2XX BLOCK OF NW 52 ST"
[117] "23 AV E / E MADISON ST" "14XX BLOCK OF N 45 ST"
[119] "15 AV NE / NE 50 ST" "24 AV E / E MONTLAKE PL E"
[121] "AURORA AV N / BRIDGE WY N" "AURORA BR / SB"
[123] "8XX BLOCK OF NE 42 ST" "40XX BLOCK OF UNIVERSITY WY NE"
[125] "38XX BLOCK OF NE 57 ST" "9XX BLOCK OF E ROANOKE ST"
[127] "4XX BLOCK OF BOYLSTON AV E" "23XX BLOCK OF EASTLAKE AV E"
[129] "4XX BLOCK OF BROADWAY E" "BURKE AV N / N NORTHLAKE WY"
[131] "5XX BLOCK OF 14 AV E" "22XX BLOCK OF NE 51 ST"
[133] "52XX BLOCK OF 22 AV NE" "N 45 ST / BURKE AV N"
[135] "LATONA AV NE / NE 58 ST" "12XX BLOCK OF 15 AV E"
[137] "15 AV E / E REPUBLICAN ST" "1 AV NE / N 56 ST"
[139] "ROOSEVELT WY NE / NE 65 ST" "43XX BLOCK OF UNIVERSITY WY NE"
[141] "85XX BLOCK OF ASHWORTH AV N" "50XX BLOCK OF 19 AV NE"
[143] "11XX BLOCK OF FAIRVIEW AV N" "5XX BLOCK OF BROADWAY E"
[145] "EASTLAKE AV E / E BOSTON ST" "34XX BLOCK OF EVANSTON AV N"
[147] "15 AV NE / NE 50 ST" "7XX BLOCK OF N 35 ST"
[149] "22 AV E / E MILLER ST" "FAIRVIEW AV N / FAIRVIEW AV E"
[151] "50XX BLOCK OF RAVENNA AV NE" "52XX BLOCK OF 15 AV NE"
[153] "55XX BLOCK OF 17 AV NE" "39 AV NE / NE 55 ST"
control <- rfeControl(functions = rfFuncs, method="cv", number=10)
results <- rfe(frame, out.factor, sizes = c(1:13), rfeControl = control) # this will take AWHILE...
Error in { : task 1 failed - "Can't have empty classes in y."
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3Igc2V0dXB9CiMgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIik7CiMgaW5zdGFsbC5wYWNrYWdlcygicmdkYWwiKTsKbGlicmFyeSh0aWR5dmVyc2UpCnJlcXVpcmUoIm1hcHMiKQpsaWJyYXJ5KGdlb3NwaGVyZSkKbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KHJnZGFsKQpsaWJyYXJ5KGNhcmV0KQpsaWJyYXJ5KGx1YnJpZGF0ZSkKaWYgKCFyZXF1aXJlKGdnbWFwKSkgeyBpbnN0YWxsLnBhY2thZ2VzKCdnZ21hcCcpOyByZXF1aXJlKGdnbWFwKSB9CnBhdGgudG8uY3N2IDwtICcuLi9NaWxlc3RvbmUgMi9TZWF0dGxlX1BvbGljZV9EZXBhcnRtZW50XzkxMV9JbmNpZGVudF9SZXNwb25zZV9PY3QxNy5jc3YnCnNwZC45MTEgPC0gcmVhZC5jc3YocGF0aC50by5jc3YsIFRSVUUpCgpzcGQuOTExJGNsZWFyYW5jZV9kYXRlX3RzID0gYXMuUE9TSVhjdChzdHJwdGltZShzcGQuOTExJEV2ZW50LkNsZWFyYW5jZS5EYXRlLCAiJW0vJWQvJVkgJUk6JU06JVMgJXAiKSkKc3BkLjkxMSRjbGVhcmFuY2VfZGF0ZV9kYXRlID0gYXMuRGF0ZShzcGQuOTExJGNsZWFyYW5jZV9kYXRlX3RzKQojIFZpZXcoc3BkLjkxMSkKCgoKIyBwYXRoIHRvIHRoZSBGT0xERVIgd2l0aCB0aGUgLnNocCBmaWxlIGluIGl0LiB0aGUgc2Vjb25kIHBhcmFtIGlzIHRoZSBuYW1lIG9mIHRoZSAuc2hwIGZpbGUKIyBzZWF0dGxlIDwtIHJlYWRPR1IoZHNuID0gcGF0aC5leHBhbmQoIn4vZG9jdW1lbnRzL0lORk8zNzAvcHJvamVjdC10ZWFtbmFtZS12Mi9tYXBzLWFwaS10ZXN0IiksIGxheWVyID0gIlNlYXR0bGVfQ2l0eV9MaW1pdHMiKQoKIyB1c2EgPC0gbWFwX2RhdGEoInN0YXRlIikKIyBkYXRhIDwtIG1lcmdlKHVzYSwgc3BkLjkxMSkKaGVyZV9sb25nIDwtICAtMTIyLjMwCmhlcmVfbGF0IDwtIDQ3LjY2CgpzZWF0dGxlID0gZ2V0X21hcChsb2NhdGlvbiA9IGMoaGVyZV9sb25nLCBoZXJlX2xhdCksIHpvb20gPSAxMywgbWFwdHlwZSA9ICdyb2FkbWFwJykKCmBgYAoKCmBgYHtyfQpzcGQuOTExIDwtIHNwZC45MTEgJT4lIAogICAgICAgICAgICAgcm93d2lzZSgpICU+JSAKICAgICAgICAgICAgIG11dGF0ZShkaXN0PWRpc3RWaW5jZW50eUVsbGlwc29pZChjKExvbmdpdHVkZSwgTGF0aXR1ZGUpLCBjKGhlcmVfbG9uZywgaGVyZV9sYXQpKSkgICAgICAgICAgICAgIApucm93KHNwZC45MTEpCgpkZXNjcmlwdGlvbnMgPC0gYygiU1RST05HIEFSTSBST0JCRVJZIiwgIlBFUlNPTiBXSVRIIEEgV0VBUE9OIChOT1QgR1VOKSIsICJIQVpBUkRTIiwgIkhBUlJBU01FTlQsIFRIUkVBVFMiLCAiRklHSFQgRElTVFVSQkFOQ0UiLCAiQ1JJU0lTIENPTVBMQUlOVCAtIEdFTkVSQUwiLCAiQVJNRUQgUk9CQkVSWSIpCgpkYXRhLnBlZCA8LSBzcGQuOTExICU+JSBmaWx0ZXIoc3RyX2RldGVjdChFdmVudC5DbGVhcmFuY2UuRGVzY3JpcHRpb24sIHBhc3RlKGRlc2NyaXB0aW9ucywgY29sbGFwc2U9InwiKSkpCiMgZGF0YS5wZWQgPC0gZGF0YS5ub3cKbnJvdyhkYXRhLnBlZCkKCmRhdGEubm93IDwtIGRhdGEucGVkICU+JSBmaWx0ZXIoY2xlYXJhbmNlX2RhdGVfdHMgPCAnMjAxNy0xMC0zMSAwMDowMDowMCcpCm5yb3coZGF0YS5ub3cpCiAgICAgICAgICAgICAgICAgIApkYXRhLmhlcmUgPC0gZGF0YS5ub3cgJT4lIGZpbHRlcihkaXN0IDwgNDYwMCkKCmRhdGEgPC0gZGF0YS5oZXJlCm5yb3coZGF0YSkKIyBWaWV3KGRhdGEpCgpnZ21hcChzZWF0dGxlKSArCiAgIGdlb21fcG9pbnQoZGF0YSA9IGRhdGEsIGFlcyh4ID0gTG9uZ2l0dWRlLCB5ID0gTGF0aXR1ZGUpLCBjb2xvdXIgPSAicmVkIiwgYWxwaGEgPSAwLjc1KQogICNjb29yZF9tYXAoKQoKYGBgCgpgYGB7cn0KZnJlcV9ieV9kZXNjIDwtIHRhYmxlKGRyb3BsZXZlbHMoZGF0YSRFdmVudC5DbGVhcmFuY2UuRGVzY3JpcHRpb24pKQojIFZpZXcoZnJlcV9ieV9kZXNjKQoKZ2dwbG90KGFzLmRhdGEuZnJhbWUoZnJlcV9ieV9kZXNjKSwgCiAgICAgICBhZXMoeCA9IFZhcjEsIHkgPSBGcmVxKSkgKwogICAgICAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScpICsjIGNyZWF0ZSBiYXIgcGxvdAogICAgY29vcmRfZmxpcCgpCgojVHJhZmZpYyByZWxhdGVkIGNhbGxzLCBzdXNwaWNpb3VzIGNpcmN1bXN0YW5jZXMsIGFuZCBkaXN0dXJiYW5jZXMgYXJlIHRoZSB0aGUgbW9zdCBzaWduaWZpY2FudCB0aHJlYXRzIHRvIHBlZGVzdHJhdGlvbnMKCiAgICAgICAgCmBgYAoKYGBge3J9CmdnbWFwKHNlYXR0bGUpICsKICBnZW9tX3BvaW50KGRhdGEgPSBkYXRhLCBhZXMoeCA9IExvbmdpdHVkZSwgeSA9IExhdGl0dWRlLCBncm91cCA9IEV2ZW50LkNsZWFyYW5jZS5EZXNjcmlwdGlvbiwgY29sb3IgPSBFdmVudC5DbGVhcmFuY2UuRGVzY3JpcHRpb24pLCBhbHBoYSA9IDAuNSkgKwogIGZhY2V0X3dyYXAofiBFdmVudC5DbGVhcmFuY2UuRGVzY3JpcHRpb24pICsKICB0aGVtZShheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIKICAgICAgICApCmBgYAoKYGBge3J9CiMgc2VsZWN0aW5nIGp1c3QgSUQgYW5kIGxvY2F0aW9uIGRhdGEKZGZfbG9jIDwtIGRhdGEgJT4lIGRwbHlyOjpzZWxlY3QoQ0FELkNEVy5JRCwgTG9uZ2l0dWRlLCBMYXRpdHVkZSkKCiMgZmlndXJpbmcgb3V0IG51bWJlciBvZiBjbHVzdGVycwp3c3MgPC0gYygpCiMgY2x1c3RlcnMgMSB0byAxNQpmb3IgKGkgaW4gMToxNSkgewogIHdzc1tpXSA8LSBzdW0oa21lYW5zKGRmX2xvYywgY2VudGVycz1pKSR3aXRoaW5zcykKfQpwbG90KDE6MTUsIHdzcywgdHlwZT0iYiIsIHhsYWI9Ik51bWJlciBvZiBDbHVzdGVycyIsCiAgeWxhYj0iV2l0aGluIGdyb3VwcyBzdW0gb2Ygc3F1YXJlcyIpCgojIGZpdHRpbmcgbW9kZWwKZml0IDwtIGttZWFucyhkZl9sb2MsIDEwKQpmaXQkY2VudGVycyAjIGxvb2sgYXQgY2x1c3RlciBzaXplcyBhbmQgbWVhbnMuIHdhbnQgY2x1c3RlcnMgdG8gYmUgYWJvdXQgZXF1YWwgc2l6ZQpmaXQkY2x1c3RlcgpjbHVzdGVyLnNpemUgPC0gZGF0YS5mcmFtZSgxOjEwLCBmaXQkc2l6ZSkKY2x1c3Rlci5zaXplCgpnZ3Bsb3QoZGF0YSA9IGNsdXN0ZXIuc2l6ZSwgYWVzKHggPSBYMS4xMCwgeSA9IGZpdC5zaXplKSkgKwogIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknKQpnZ3Bsb3QoKQpnZ21hcChzZWF0dGxlKSArCiAgZ2VvbV9wb2ludChkYXRhID0gYXMuZGF0YS5mcmFtZShmaXQkY2VudGVycyksIGFlcyh4ID0gTG9uZ2l0dWRlLCB5ID0gTGF0aXR1ZGUpLCBhbHBoYSA9IDAuNSkKIyBsb29raW5nIGF0IGNsdXN0ZXIgbWVhbnMKYWdncmVnYXRlKGRmX2xvYywgYnk9bGlzdChmaXQkY2x1c3RlciksIEZVTj1tZWFuKQoKZGZfbG9jCgojIGFkZGluZyBkYXRhIGJhY2sgaW50byBkYXRhZnJhbWUgCiMgZGZfbG9jIDwtIGRmX2xvYyAlPiUgbXV0YXRlKGNsdXN0ZXIgPSBmaXQkY2x1c3RlcikgCmRhdGEkY2x1c3RlciA8LSBmaXQkY2x1c3RlcgoKIyBWaWV3KGRhdGEpCmBgYAoKYGBge3J9CiMgdGltZXN0YW1wIC0+ICB5ZWFyICBtb250aCBkYXkgaG91ciAgbWludXRlCiMgc2VjdG9yIC0+IHRvIGZhY3RvciAodGhlcmUgYXJlIDE3IHNlY3RvcnMpCiMgYmVhdCAtPiB0byBmYWN0b3IgKHRoZXJlIGFyZSAzIGJlYXRzIHBlciBzZWN0b3IpCgojIGNsZWFuIHRoZSBkYXRhIGEgYml0IG1vcmUKZGF0YSRldmVudF9jbGVhcmFuY2VfdHMgPSBhcy5QT1NJWGN0KHN0cnB0aW1lKGRhdGEkRXZlbnQuQ2xlYXJhbmNlLkRhdGUsICIlbS8lZC8lWSAlSTolTTolUyAlcCIpKQpkYXRhJGV2ZW50X2NsZWFyYW5jZV9kYXRlID0gYXMuRGF0ZShkYXRhJGV2ZW50X2NsZWFyYW5jZV90cykKZGF0YSRldmVudF9jbGVhcmFuY2VfbW9udGggPSBtb250aCh5bWRfaG1zKGFzLmNoYXJhY3RlcihkYXRhJGV2ZW50X2NsZWFyYW5jZV90cykpKQpkYXRhJGV2ZW50X2NsZWFyYW5jZV9kYXkgPSB3ZWVrZGF5cyhkYXRhJGV2ZW50X2NsZWFyYW5jZV9kYXRlKQpkYXRhJGV2ZW50X2NsZWFyYW5jZV9ociA9IGhvdXIoeW1kX2htcyhhcy5jaGFyYWN0ZXIoZGF0YSRldmVudF9jbGVhcmFuY2VfdHMpKSkKZGF0YSRldmVudF9jbGVhcmFuY2VfbW4gPSBtaW51dGUoeW1kX2htcyhhcy5jaGFyYWN0ZXIoZGF0YSRldmVudF9jbGVhcmFuY2VfdHMpKSkKZGF0YSRJbml0aWFsLlR5cGUuR3JvdXAgPSBmYWN0b3IoZGF0YSRJbml0aWFsLlR5cGUuR3JvdXApCmRhdGEkRXZlbnQuQ2xlYXJhbmNlLkdyb3VwID0gZmFjdG9yKGRhdGEkRXZlbnQuQ2xlYXJhbmNlLkdyb3VwKQpkYXRhJFpvbmUuQmVhdCA9IGZhY3RvcihkYXRhJFpvbmUuQmVhdCkKZGF0YSREaXN0cmljdC5TZWN0b3IgPSBmYWN0b3IoZGF0YSREaXN0cmljdC5TZWN0b3IpCmRhdGEkZXZlbnRfY2xlYXJhbmNlX2RheSA9IGZhY3RvcihkYXRhJGV2ZW50X2NsZWFyYW5jZV9kYXkpCmRhdGEKCmNvbC5uYW1lcyA8LSBwYXN0ZShjKAogICJFdmVudC5DbGVhcmFuY2UuQ29kZSIKICAsICJjbHVzdGVyIgogICwgIkNlbnN1cy5UcmFjdCIKICAsICJldmVudF9jbGVhcmFuY2VfZGF5IgogICwgIkV2ZW50LkNsZWFyYW5jZS5Hcm91cCIKICAsICJFdmVudC5DbGVhcmFuY2UuU3ViR3JvdXAiCiAgLCAiRGlzdHJpY3QuU2VjdG9yIgogICwgIlpvbmUuQmVhdCIKICAjLCAiZXZlbnRfY2xlYXJhbmNlX3RzIgogICMgLCJJbmNpZGVudC5Mb2NhdGlvbiIKICAsICJldmVudF9jbGVhcmFuY2VfaHIiCiAgLCAiZXZlbnRfY2xlYXJhbmNlX21uIgogICwgImV2ZW50X2NsZWFyYW5jZV9tb250aCIgCiAgLCAiSHVuZHJlZC5CbG9jay5Mb2NhdGlvbiIKICApLCBjb2xsYXBzZT0ifCIpCmNvbHMgPC0gZ3JlcChjb2wubmFtZXMsIGNvbG5hbWVzKGRhdGEpKQpjb2xzCiMgY29ycl9tYXRyaXggPC0gY29yKGRhdGFbLGNvbHNdKSAjIGNvcnJlbGF0aW9ucyBiZXR3ZWVuIGFsbCBwcmVkaWN0b3IgdmFycwojIGNvcnJfbWF0cml4CgojIGN1dG9mZiA8LSAwLjUgIyBzaG91bGQgYmUgaGlnaGVyIGluIHByYWN0aWNlCgojIGhpZ2hseV9jb3JyIDwtIGZpbmRDb3JyZWxhdGlvbihjb3JyX21hdHJpeCwgY3V0b2ZmPWN1dG9mZikKIyBwcmludChjb2xuYW1lcyhzcGQuOTExKVtoaWdobHlfY29ycl0pICMgYWdlIGlzIGhpZ2hseSBjb3JyZWFsdGVkIHdpdGggcHJlZ25hbnQKCnRyYWluLmRhdGEgPC0gc2VsZWN0KGRhdGEsIGNvbHMpCnRyYWluLmRhdGEKIyBkYXRhIDwtIGRhdGEgJT4lIGRyb3BsZXZlbHMoKQoKIyBncmVwKCJIdW5kcmVkLkJsb2NrLkxvY2F0aW9uIiwgY29sbmFtZXModHJhaW4uZGF0YSksIGludmVydCA9IFQpCgpwcmVkaWN0b3JzIDwtIGdyZXAoIkh1bmRyZWQuQmxvY2suTG9jYXRpb24iLCBjb2xuYW1lcyh0cmFpbi5kYXRhKSwgaW52ZXJ0ID0gVCkKb3V0Y29tZSA8LSBncmVwKCJIdW5kcmVkLkJsb2NrLkxvY2F0aW9uIiwgY29sbmFtZXModHJhaW4uZGF0YSkpCgojIHRyYWluLmRhdGFbLHByZWRpY3RvcnNdCmZyYW1lIDwtIGRhdGEuZnJhbWUodHJhaW4uZGF0YVsscHJlZGljdG9yc10pCmZyYW1lCm91dC5mYWN0b3IgPC0gdHJhaW4uZGF0YSRIdW5kcmVkLkJsb2NrLkxvY2F0aW9uCmFzLnZlY3RvcihvdXQuZmFjdG9yKQoKCmNvbnRyb2wgPC0gcmZlQ29udHJvbChmdW5jdGlvbnMgPSByZkZ1bmNzLCBtZXRob2Q9ImN2IiwgbnVtYmVyPTEwKQpyZXN1bHRzIDwtIHJmZShmcmFtZSwgb3V0LmZhY3Rvciwgc2l6ZXMgPSBjKDE6MTMpLCByZmVDb250cm9sID0gY29udHJvbCkgIyB0aGlzIHdpbGwgdGFrZSBBV0hJTEUuLi4KCnJlc3VsdHMKZ2dwbG90KHJlc3VsdHMpCgojIGNob3NlbiBmZWF0dXJlcwpwcmVkaWN0b3JzKHJlc3VsdHMpCmBgYAo=